// 移动端微信小程序手势锁功能
class Gesture {
  constructor(page, options = {}) {
    this.canvasId = options.canvasId || 'gestureCanvas'; // canvas 的 id 可配置
    this.canvasNode = null;
    this.customWidth = options.width || null; // 用户自定义宽度
    this.page = page; // 页面实例
    this.displayWidth = null;
    this.displayHeight = null;
    this.ctx = null;
    this.points = []; // 九宫格点
    this.selected = [];
    this.radius = options.radius || 10; // 圆点半径可配置
    this.touching = false;
    this.lineColor = options.lineColor || '#2196f3'; // 线条颜色可配置，默认半透明黑色
    this.lineWidth = options.lineWidth || 6; // 线条宽度可配置
    this.pointColor = options.pointColor || '#ccc';
    this.activeColor = options.activeColor || '#2196f3';
    this.errorColor = options.errorColor || '#f40'; // 错误时的颜色
    this.minPoints = options.minPoints || 4; // 最小连接点数
    this.followLine = { x: null, y: null }; // 跟随手指的线
    this.errorLine = false; // 错误状态
    this.init();
  }

  async init() {
    const query = wx.createSelectorQuery().in(this.page)
    const canvas = await new Promise((resolve) => {
      query
        .select("#" + this.canvasId)
        .fields({ node: true, size: true })
        .exec((res) => {
          resolve(res[0])
        })
    })

    // 获取 canvas 实例
    const canvasNode = canvas.node
    this.canvasNode = canvasNode;
    const dpr = wx.getSystemInfoSync().pixelRatio;

    // 计算实际渲染尺寸
    const nodeWidth = canvas.width

    // 如果用户指定了宽度，使用用户指定的宽度，否则使用节点宽度
    this.displayWidth = this.customWidth || nodeWidth
    // 确保是正方形
    this.displayHeight = this.displayWidth

    // 设置 canvas 的实际渲染尺寸（乘以设备像素比）
    canvasNode.width = this.displayWidth * dpr
    canvasNode.height = this.displayWidth * dpr

    this.ctx = canvasNode.getContext('2d');
    this.ctx.scale(dpr, dpr);
    this.initPoints();
    this.draw();
  }

  initPoints() {
    // 计算九宫格点坐标
    this.points = [];
    const offsetX = this.displayWidth / 4;
    const offsetY = this.displayHeight / 4;
    for (let row = 1; row <= 3; row++) {
      for (let col = 1; col <= 3; col++) {
        this.points.push({
          x: offsetX * col,
          y: offsetY * row,
          index: (row - 1) * 3 + col
        });
      }
    }
  }

  draw() {
    const ctx = this.ctx;
    ctx.clearRect(0, 0, this.displayWidth, this.displayHeight);
    // 画已选连线
    if (this.selected.length > 0) {
      ctx.beginPath();
      ctx.lineCap = 'round';
      ctx.lineJoin = 'round'; // 关键：折线圆角
      ctx.moveTo(this.selected[0].x, this.selected[0].y);
      for (let i = 1; i < this.selected.length; i++) {
        ctx.lineTo(this.selected[i].x, this.selected[i].y);
      }
      if (this.touching && this.followLine.x !== null && this.followLine.y !== null) {
        ctx.lineTo(this.followLine.x, this.followLine.y);
      }
      ctx.strokeStyle = this.errorLine ? this.errorColor : this.lineColor; // 错误时红色
      ctx.lineWidth = this.lineWidth;
      ctx.stroke();
      ctx.closePath();
    }
    // 画所有点
    this.points.forEach(pt => {
      ctx.beginPath();
      ctx.arc(pt.x, pt.y, this.radius, 0, 2 * Math.PI);
      // 错误时已选点变红色
      if (this.errorLine && this.isPointSelected(pt)) {
        ctx.fillStyle = this.errorColor;
      } else {
        ctx.fillStyle = this.isPointSelected(pt) ? this.activeColor : this.pointColor;
      }
      ctx.fill();
      ctx.closePath();
    });
  }

  isPointSelected(pt) {
    return this.selected.some(s => s.index === pt.index);
  }

  getTouchPoint(x, y) {
    return this.points.find(pt =>
      Math.pow(pt.x - x, 2) + Math.pow(pt.y - y, 2) < Math.pow(this.radius, 2)
    );
  }

  onTouchStart(e) {
    const { x, y } = e.touches[0];
    const pt = this.getTouchPoint(x, y);
    this.selected = [];
    this.followLine = { x: null, y: null };
    if (pt) {
      this.selected = [pt];
      this.touching = true;
      this.draw();
    }
  }

  onTouchMove(e) {
    if (!this.touching) return;
    const { x, y } = e.touches[0];
    this.followLine = { x, y };
    const pt = this.getTouchPoint(x, y);
    if (pt && !this.isPointSelected(pt)) {
      this.selected.push(pt);
    }
    this.draw();
  }

  onTouchEnd() {
    this.touching = false;
    this.followLine = { x: null, y: null };
    if (this.selected.length < this.minPoints) {
      wx.showToast({ title: `请至少连接${this.minPoints}个点`, icon: 'none' });
      this.errorLine = true;
      this.draw();
      setTimeout(() => {
        this.errorLine = false;
        this.selected = [];
        this.draw();
      }, 500);
    } else {
      const gesture = this.selected.map(pt => pt.index).join('');
      console.log('手势锁:', gesture);
      // 在这里可以进行手势校验逻辑
      // TODO: 校验 gesture
      const isCorrect = false; // 这里替换为校验逻辑
      if (!isCorrect) {
        this.errorLine = true;
        this.draw();
        setTimeout(() => {
          this.errorLine = false;
          this.selected = [];
          this.draw();
        }, 500);
      } else {
        // 正确逻辑
        this.selected = [];
        this.draw();
      }
    }
  }
}

export default Gesture